<?php
namespace Opencart\System\Engine;
/**
 * Router class
 */
class Router {
	private $registry;
	private $pre_action = [];
	private $error;

	/**
	 * Constructor
	 *
	 * @param    object  $registry
	 */
	public function __construct($registry) {
		$this->registry = $registry;
	}

	/**
	 * Add a pre action to run before the main action
	 *
	 * @param    object  $pre_action
	 */
	public function addPreAction($pre_action) {
		$this->pre_action[] = $pre_action;
	}

	/**
	 * Dispatch the action
	 *
	 * @param    object  $action
	 * @param    string  $error
	 *
	 * @return   object
	 */
	public function dispatch($action, $error) {
		$this->error = $error;

		foreach ($this->pre_action as $pre_action) {
			$result = $this->execute($pre_action);

			if ($result instanceof \Exception) {
				return $result;
			}
		}

		while ($action) {
			$action = $this->execute($action);
		}
	}

	/**
	 * Execute an action
	 *
	 * @param    string  $action
	 *
	 * @return   mixed
	 */
	private function execute($action) {
		if (!$action instanceof \Opencart\System\Engine\Action) {
			return new \Exception('Error: Could not call route ' . $action . '!');
		}

		// Stop any magical methods being called
		if (substr($action->getMethod(), 0, 2) == '__') {
			return new \Exception('Error: Calls to magic methods are not allowed!');
		}

		$file = $action->getFile();
		$class = $action->getClass();
		$method = $action->getMethod();
		$args = $action->getArgs();

		$path = '';

		$parts = explode('/', str_replace('\\', '/', $file));

		foreach ($parts as $part) {
			$path .= $part;

			if (is_dir($path)) {
				$path .= '/';

				continue;
			}

			if (is_file($path)) {
				include_once($path);

				break;
			}
		}

		if (!class_exists($class)) {
			return new \Exception('Error: Could not call route ' . $class . '!');
		}

		$controller = new $class($this->registry);

		if (!method_exists($controller, $method)) {
			return new \Exception('Error: Could not call route ' . $method . '!');
		}

		if (!is_callable([$controller, $method])) {
			return new \Exception('Error: Could not call route ' . $method . '!');
		}

		return call_user_func_array([$controller, $method], $args);
	}
}
